/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.ee.cybertron.energon.beans;

import com.ee.cybertron.databasemodule.DataBaseConnection;
import com.ee.cybertron.energon.base.ServicioBase;
import com.ee.cybertron.energon.components.*;
import com.ee.cybertron.energon.loader.LoaderCreateForm;
import com.ee.cybertron.energon.daemon.DaemonMessage;
import com.ee.cybertron.energon.model.Mensaje;
import com.ee.cybertron.energon.model.Prime;
import com.ee.cybertron.energon.model.User;
import com.ee.cybertron.energon.util.Mensajes;
import com.icesoft.faces.component.ext.HtmlPanelGroup;
import com.icesoft.faces.component.menubar.MenuItem;
import com.icesoft.faces.context.DisposableBean;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.faces.event.PhaseId;
import org.jdom.JDOMException;

/**
 *
 * @author stevenziggiz
 */
public class BeanProviderWorkArea implements DisposableBean {

    ServicioBase service;
    private List<MenuItem> menuList;
    private List<Prime> primeList;
    private String user;
    private String password;
    private CyberPanelGroup panelActual;
    private HtmlPanelGroup panel;
    private String navegation;
    private User userLogin;
    DaemonMessage daemonMessage;
    private List<Mensaje> messageList;
    private boolean welcome;

    public BeanProviderWorkArea() {
        service = new ServicioBase();
        messageList = new ArrayList<Mensaje>();
    }

    /**
     * Load the prime list
     *
     * @return Return all elements of data base table @code{Prime}
     */
    private List<Prime> loadPrimeList() {
        return service.seleccionar(Prime.class);
    }

    /**
     * Load the local menu, it reads the elements of @code{primeList} and
     * creates the menu.
     *
     * @return Return the menu
     */
    public List<MenuItem> loadMenu() {
        MenuItem menuItemChild = new MenuItem();;
        MenuItem menuItem = new MenuItem();
        menuItem.setValue("Casos");
        List<MenuItem> menuItemList = new ArrayList<MenuItem>();
        menuItemChild.setValue("Inicio");
        menuItemChild.setAction(FacesContext.getCurrentInstance().getApplication().createMethodBinding("#{beanProviderWorkArea.actionMenu2}", new Class[]{}));
        menuItemList.add(menuItemChild);
        for (Prime prime : primeList) {
            menuItemChild = new MenuItem();
            menuItemChild.setValue(prime.getDescription());
            menuItemChild.setActionListener(FacesContext.getCurrentInstance().getApplication().createMethodBinding("#{beanProviderWorkArea.actionListenerMenu}", new Class[]{ActionEvent.class}));
            menuItemChild.setAction(FacesContext.getCurrentInstance().getApplication().createMethodBinding("#{beanProviderWorkArea.actionMenu}", new Class[]{}));
            menuItem.getChildren().add(menuItemChild);
        }
        menuItemList.add(menuItem);
        menuItemChild = new MenuItem();
        menuItemChild.setValue("Salir");
        menuItemChild.setAction(FacesContext.getCurrentInstance().getApplication().createMethodBinding("#{beanProviderWorkArea.actionMenu3}", new Class[]{}));
        menuItemList.add(menuItemChild);
        return menuItemList;
    }

    /**
     * This method is responsible to find the prime selected for the user on the
     * menu option
     *
     * @param navegationSelected Receives the the menu option selected for the
     * user
     */
    private void primeSelected(String navegationSelected) {
        InputStream inputStream;
        for (Prime prime : primeList) {
            if (prime.getDescription().equals(navegationSelected)) {
                inputStream = new ByteArrayInputStream(prime.getPrime());
                createForm(inputStream);
                break;
            }
        }
    }

    /**
     * This method is responsible to create the correct form according the menu
     * option selected and the user's profile.
     *
     * @param inputStream
     * @param profile
     */
    public void createForm(InputStream inputStream) {
        try {
            LoaderCreateForm ctrlCreateForm = new LoaderCreateForm();
            CyberPanelGroup cyberPanelGroup = ctrlCreateForm.createRoleForm(inputStream);
            cyberPanelGroup.rendered(userLogin);
            setPanelActual(cyberPanelGroup);
        } catch (JDOMException ex) {
            Logger.getLogger(BeanProviderWorkArea.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            Logger.getLogger(BeanProviderWorkArea.class.getName()).log(Level.SEVERE, null, ex);
        } catch (InstantiationException ex) {
            Logger.getLogger(BeanProviderWorkArea.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalAccessException ex) {
            Logger.getLogger(BeanProviderWorkArea.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    private void reset() {
        primeList = loadPrimeList();
        menuList = loadMenu();
    }

    /**
     *
     * @param event
     */
    public void actionListenerMenu(ActionEvent event) {
        MenuItem temp;
        if (event.getPhaseId() != PhaseId.INVOKE_APPLICATION) {
            event.setPhaseId(PhaseId.INVOKE_APPLICATION);
            event.queue();
        } else {
            panel = new HtmlPanelGroup();
            temp = (MenuItem) event.getSource();
            this.navegation = temp.getValue().toString();
            primeSelected(navegation);
        }
    }

    public String actionMenu() {
        welcome = false;
        return "new case";
    }

    public String actionMenu2() {
        reset();
        welcome = true;
        return "welcome";
    }

    public String actionMenu3() {
        welcome = false;
        if (daemonMessage != null) {
            daemonMessage.stop();
            daemonMessage = null;
        }
        userLogin = null;
        primeList = null;
        menuList = null;
        return "login";
    }

    public String actionButtonAccept() {
        String message = "Error";
        String SQLInsert = "INSERT INTO ";
        String SQLUpDate = "UPDATE ";
        CyberPanelCollapsible panelCollapsible;
        List<UIComponent> panelCollapsibleList = panel.getChildren().get(0).getChildren();
        for (UIComponent uIComponent : panelCollapsibleList) {
            panelCollapsible = (CyberPanelCollapsible) uIComponent;
            if ((panelCollapsible.getTypeForm().equals("creator")) && (panelCollapsible.getRole().equals(userLogin.getIdProfile().getName()))) {
                SQLInsert = createSQLInsert(SQLInsert + panelCollapsible.getTableReference(), uIComponent.getChildren().get(0).getChildren());
                service.executeQuery(SQLInsert);
                createMessageForProfile(panelCollapsible.getTableReference());
                message = "Se ha guardado correctarmente el caso.";
            } else {
                if ((panelCollapsible.getTypeForm().equals("approver")) && (panelCollapsible.getRole().equals(userLogin.getIdProfile().getName()))) {
                    SQLUpDate = createSQLUpDate(SQLUpDate + panelCollapsible.getTableReference() + " SET ", uIComponent.getChildren().get(0).getChildren());
                    SQLUpDate += " WHERE " + panelCollapsible.getColumnId() + "=" + panelCollapsible.getValueColumnId() + ";";
                    service.executeQuery(SQLUpDate);
                    deleteMessage(panelCollapsible.getTableReference(), panelCollapsible.getColumnId(), panelCollapsible.getValueColumnId(), panelCollapsible.getRole());
                    message = "Se ha aprobado correctamente el caso.";
                }
            }
        }
        reset();
        welcome = true;
        Mensajes.agregarInfo(message);
        return "welcome";
    }

    /**
     * Creates the message to display the next profile
     *
     * @param tableReference
     */
    private void createMessageForProfile(String tableReference) {
        String nombreTableId;
        Integer idLastInsert;
        Mensaje mensaje = new Mensaje();
        nombreTableId = new DataBaseConnection().obtainColumnPrimaryKey("cybertron", tableReference);
        idLastInsert = (Integer) service.executeQueryR("Select MAX(" + nombreTableId + ") From " + tableReference, null);
        mensaje.setIdTabla(idLastInsert);
        mensaje.setNombreId(nombreTableId);
        mensaje.setNombreTabla(tableReference);
        mensaje.setRole(nextRole());
        mensaje.setDescripcionProceso("Tiene pendientes en " + navegation);
        service.guardar(mensaje);
    }

    private void deleteMessage(String nombreTabla, String nombreId, Integer idTabla, String role) {
        service.executeQuery("DELETE FROM mensaje WHERE idtabla=" + idTabla + " AND nombreid='" + nombreId + "' AND nombreTabla='" + nombreTabla + "' AND role='" + role + "';");
    }

    /**
     * Find the next profile in the process
     *
     * @return
     */
    public String nextRole() {
        CyberPanelCollapsible panelCollapsible;
        for (int i = 0; i < panel.getChildren().get(0).getChildCount(); i++) {
            panelCollapsible = (CyberPanelCollapsible) panel.getChildren().get(0).getChildren().get(i);
            if (panelCollapsible.getRole().equals(userLogin.getIdProfile().getName())) {
                return ((CyberPanelCollapsible) panel.getChildren().get(0).getChildren().get(i + 1)).getRole();
            }
        }
        return null;
    }

    /**
     * Creates the script for the insertion of the new data.
     *
     * @param SQLInsert
     * @param componentsList
     * @return
     */
    private String createSQLInsert(String SQLInsert, List<UIComponent> componentsList) {
        CyberInputText inputText;
        CyberSelectOneMenu selectOneMenu;
        String values = " values (";
        String SQLInsertColumns = " (";
        for (UIComponent uIComponent : componentsList) {
            if (uIComponent instanceof CyberInputText) {
                inputText = (CyberInputText) uIComponent;
                if (SQLInsertColumns.equals(" (")) {
                    SQLInsertColumns += inputText.getColumnReference();
                } else {
                    SQLInsertColumns += "," + inputText.getColumnReference();
                }
                if (inputText.getDataType().equals("String")) {
                    if (values.equals(" values (")) {
                        values += "'" + inputText.getValue() + "'";
                    } else {
                        values += ",'" + inputText.getValue() + "'";
                    }
                } else {
                    if (values.equals(" values (")) {
                        values += inputText.getValue();
                    } else {
                        values += "," + inputText.getValue();
                    }
                }
            } else {
                if (uIComponent instanceof CyberSelectOneMenu) {
                    selectOneMenu = (CyberSelectOneMenu) uIComponent;
                    if (SQLInsertColumns.equals(" (")) {
                        SQLInsertColumns += selectOneMenu.getOptionValueReference();
                    } else {
                        SQLInsertColumns += "," + selectOneMenu.getOptionValueReference();
                    }
                    if (selectOneMenu.getDataType().equals("String")) {
                        if (values.equals(" values (")) {
                            values += "'" + selectOneMenu.getValue() + "'";
                        } else {
                            values += ",'" + selectOneMenu.getValue() + "'";
                        }
                    } else {
                        if (values.equals(" values (")) {
                            values += selectOneMenu.getValue();
                        } else {
                            values += "," + selectOneMenu.getValue();
                        }
                    }
                }
            }
        }
        SQLInsertColumns += " )";
        values += ")";
        return SQLInsert + " " + SQLInsertColumns + " " + values;
    }

    private String createSQLUpDate(String SQLUpDate, List<UIComponent> componentsList) {
        CyberInputText inputText;
        CyberSelectOneMenu selectOneMenu;
        String values = " ";
        for (UIComponent uIComponent : componentsList) {
            if (uIComponent instanceof CyberInputText) {
                inputText = (CyberInputText) uIComponent;
                if (inputText.getDataType().equals("String")) {
                    if (values.equals(" ")) {
                        values += inputText.getColumnReference() + "='" + inputText.getValue() + "'";
                    } else {
                        values += "," + inputText.getColumnReference() + "='" + inputText.getValue() + "'";
                    }
                } else {
                    if (values.equals(" values (")) {
                        values += inputText.getColumnReference() + "=" + inputText.getValue();
                    } else {
                        values += "," + inputText.getColumnReference() + "=" + inputText.getValue();
                    }
                }
            } else {
                if (uIComponent instanceof CyberSelectOneMenu) {
                    selectOneMenu = (CyberSelectOneMenu) uIComponent;
                    if (selectOneMenu.getDataType().equals("String")) {
                        if (values.equals(" ")) {
                            values += selectOneMenu.getOptionValueReference() + "='" + selectOneMenu.getValue() + "'";
                        } else {
                            values += "," + selectOneMenu.getOptionValueReference() + "='" + selectOneMenu.getValue() + "'";
                        }
                    } else {
                        if (values.equals(" ")) {
                            values += selectOneMenu.getOptionValueReference() + "=" + selectOneMenu.getValue();
                        } else {
                            values += "," + selectOneMenu.getOptionValueReference() + "=" + selectOneMenu.getValue();
                        }
                    }
                }
            }
        }
        return SQLUpDate + values;
    }

    public String actionButtonLogin() {
        userLogin = (User) service.obtenerElemento("User.findByUserPassword", user, password);
        if (userLogin != null) {
            primeList = loadPrimeList();
            menuList = loadMenu();
            if (userLogin.getIdProfile().getName().equals("manager")) {
                daemonMessage = new DaemonMessage();
                daemonMessage.start();
            }
            welcome = true;
            return "welcome";
        } else {
            welcome = false;
            return "login";
        }
    }

    public void dispose() throws Exception {
        try {
            this.finalize();
        } catch (Throwable ex) {
            Logger.getLogger(BeanProviderWorkArea.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    @Override
    public void finalize() throws Throwable {
        super.finalize();
        panelActual = null;
        panel = null;
    }

    /**
     * @return the panel
     */
    public HtmlPanelGroup getPanel() {
        if (panelActual != null) {
            this.panel.getChildren().clear();
            this.panel.getChildren().add(panelActual);
        }
        return panel;
    }

    /**
     * @param panel the panel to set
     * @deprecated
     */
    @Deprecated
    public void setPanel(HtmlPanelGroup panel) {
        this.panel = panel;
    }

    /**
     * @return the panelActual
     */
    public CyberPanelGroup getPanelActual() {
        return panelActual;
    }

    /**
     * @param panelActual the panelActual to set
     */
    public void setPanelActual(CyberPanelGroup panelActual) {
        this.panelActual = panelActual;
        this.panel.getChildren().clear();
        this.panel.getChildren().add(panelActual);
    }

    /**
     * @return the user
     */
    public String getUser() {
        return user;
    }

    /**
     * @param user the user to set
     */
    public void setUser(String user) {
        this.user = user;
    }

    /**
     * @return the password
     */
    public String getPassword() {
        return password;
    }

    /**
     * @param password the password to set
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * @return the menuList
     */
    public List<MenuItem> getMenuList() {
        return menuList;
    }

    /**
     * @param menuList the menuList to set
     */
    public void setMenuList(List<MenuItem> menuList) {
        this.menuList = menuList;
    }

    /**
     * @return the primeList
     */
    public List<Prime> getPrimeList() {
        return primeList;
    }

    /**
     * @param primeList the primeList to set
     */
    public void setPrimeList(List<Prime> primeList) {
        this.primeList = primeList;
    }

    /**
     * @return the navegation
     */
    public String getNavegation() {
        return navegation;
    }

    /**
     * @param navegation the navegation to set
     */
    public void setNavegation(String navegation) {
        this.navegation = navegation;
    }

    /**
     * @return the userLogin
     */
    public User getUserLogin() {
        return userLogin;
    }

    /**
     * @param userLogin the userLogin to set
     */
    public void setUserLogin(User userLogin) {
        this.userLogin = userLogin;
    }

    /**
     * @return the messageList
     */
    public List<Mensaje> getMessageList() {
        return messageList;
    }

    /**
     * @param messageList the messageList to set
     */
    public void setMessageList(List<Mensaje> messageList) {
        this.messageList = messageList;
    }

    /**
     * @return the welcome
     */
    public boolean isWelcome() {
        return welcome;
    }

    /**
     * @param welcome the welcome to set
     */
    public void setWelcome(boolean welcome) {
        this.welcome = welcome;
    }
}
